/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.ui.dialogs;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.PackageableElement;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.UMLFactory;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.utils.ClassElementComparator;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.core.utils.LookForElement;

/**
 * 
 */
public class ChooseSetMetaclassDialog extends ChooseSetAssistedDialog  implements IChooseDialog{
	// private ArrayList allPossibilities;
	
	/**
	 * parent profile (top Profile).
	 */
	protected Profile profile;
	
	/**
	 * @param parentShell 
	 * @param profile 
	 */
	public ChooseSetMetaclassDialog(Shell parentShell, Profile profile){
		this(parentShell, profile, true);
	}
	
	
	/**
	 * 
	 * 
	 * @param parentShell 
	 * @param profile 
	 */
	public ChooseSetMetaclassDialog(Shell parentShell, Profile profile, boolean retrieveImported){
		super(parentShell,
				"Meta classes: ",
				"Imported meta-classes: ");
		
		this.profile=profile;
		// replace selectedElementList with a new one, that has a special comparator 
		selectedElementList = new ElementListWithComparator(new ClassElementComparator());
		
		labelProvider = new MetaclassLabelProvider();
		decoratedContentProposalProvider = new MetaclassContentProposalProvider();
		
		if(retrieveImported) {
			Iterator metaclasses = profile.getReferencedMetaclasses().iterator();
			while (metaclasses.hasNext()){
				selectedElementList.addElement(metaclasses.next());
			}
		}
		
		Iterator metaclasses = LookForElement.getPossibleMetaclasses(profile).iterator();
		while (metaclasses.hasNext()){
			Object currentPossibleMetaclass = metaclasses.next();
			
			// for each element in the metaclasses collection, check if this class is not already imported
			if(!selectedElementList.contains(currentPossibleMetaclass)) {
				possibleElementList.addElement(currentPossibleMetaclass);
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.dialogs.ChooseSetAssistedDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
	 */
	/**
	 * 
	 * 
	 * @param parent 
	 * 
	 * @return 
	 */
	protected Control createDialogArea(Composite parent) {
		Control composite = super.createDialogArea(parent);
		
		// Add 2 columns to the table area
		// possibleElementsTable.setLinesVisible(true);
		possibleElementsTable.setHeaderVisible(true);

		// 1st column with image/checkboxes - NOTE: The SWT.CENTER has no effect!!
		TableColumn column = new TableColumn(possibleElementsTable, SWT.CENTER, 0);		
		column.setText("Metaclass");
		column.setWidth(150);
		column.addSelectionListener(new SelectionAdapter() {
	       	
			public void widgetSelected(SelectionEvent e) {
				possibleElementsTableViewer.setSorter(new AlphabeticalViewerSorter(0));
			}
		});
		
		// 2nd column with task Description
		column = new TableColumn(possibleElementsTable, SWT.LEFT, 1);
		column.setText("Information");
		column.setWidth(165);
		// Add listener to column so tasks are sorted by description when clicked 
		column.addSelectionListener(new SelectionAdapter() {
       	
			public void widgetSelected(SelectionEvent e) {
				possibleElementsTableViewer.setSorter(new AlphabeticalViewerSorter(1));
			}
		});

		// set sorter to the possible element table viewer 
		possibleElementsTableViewer.setSorter(new AlphabeticalViewerSorter(0));
		
		return composite;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.dialogs.ChooseSetAssistedDialog#runAddElement(java.lang.String)
	 */
	/**
	 * 
	 * 
	 * @param name 
	 */
	protected void runAddElement(String name) {
		// find the class in the list
		Class theClass = null;
		Iterator it = possibleElementList.getElements().iterator();
		while (it.hasNext()) {
			Class current = (Class) it.next();
			if( name.equalsIgnoreCase(current.getName()) || name.equalsIgnoreCase(current.getQualifiedName())) {
				theClass = current;
			}
		}
		if(theClass != null) {
			runActionAdd(theClass);
		}
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.dialogs.ChooseSetAssistedDialog#isSelectableElement(java.lang.String)
	 */
	/**
	 * 
	 * 
	 * @param text 
	 * 
	 * @return 
	 */
	protected boolean isSelectableElement(String text) {
		// iterate through all possibilities and return true if text corresponds
		Iterator it = possibleElementList.getElements().iterator();
		while (it.hasNext()) {
			Class element = (Class) it.next();
			if( text.equalsIgnoreCase(element.getName()) || text.equalsIgnoreCase(element.getQualifiedName())) {
				return true;
			}
		}
		return false;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.utils.dialog.ChooseSetDialog#okPressed()
	 */
	/**
	 * 
	 */
	@Override
	protected void okPressed(){
		applyModifications();
		super.okPressed();
	}
	
	
	/**
	 * Apply modification when the button ok is pressed.
	 */
	protected void applyModifications() {
		EList metaclassSet= profile.getReferencedMetaclasses();
		for(int i=0;i<metaclassSet.size();i++){
			if(!selectedElementList.contains(metaclassSet.get(i))){
				Debug.debug(this, "To delete: "+metaclassSet.get(i), channel);
				org.eclipse.uml2.uml.Class theClass=(org.eclipse.uml2.uml.Class)metaclassSet.get(i);
				 //themodel.getReferencedMetaclasses().remove(metaclassSet.get(i));
				EList importSet=profile.getElementImports();
				for (int j=0; j<importSet.size();j++){
					if(((org.eclipse.uml2.uml.Class)
							((org.eclipse.uml2.uml.ElementImport)importSet.get(j)).getImportedElement())
							.equals(theClass)){
						profile.getElementImports().remove(j);
					}
				}
			}
		}
		for(int i=0;i<selectedElementList.getElements().size();i++){
			if(!metaclassSet.contains(selectedElementList.getElements().get(i))){
				Debug.debug(this, "To add: "+selectedElementList.getElements().get(i), channel);
				//ElementImport ei=themodel.createMetaclassReference((PackageableElement)metaclassesreference.get(i)); ca ne focntionne plus!!
				ElementImport ei= UMLFactory.eINSTANCE.createElementImport();				
				ei.setImportedElement((PackageableElement)selectedElementList.getElements().get(i));
				ei.setAlias(((NamedElement)selectedElementList.getElements().get(i)).getName());
				//themodel.getPackagedElements().add((PackageableElement)metaclassesreference.get(i));
				profile.getMetaclassReferences().add(ei);
			}
		}
	}


	/**
	 * 
	 */
	public class MetaclassContentProposalProvider extends DecoratedContentProposalProvider {

		/* (non-Javadoc)
		 * @see com.cea.papyrus.core.ui.dialogs.ChooseSetAssistedDialog.DecoratedContentProposalProvider#getProposals(java.lang.String, int)
		 */
		/**
		 * 
		 * 
		 * @param contents 
		 * @param position 
		 * 
		 * @return 
		 */
		public DecoratedContentProposal[] getProposals(String contents, int position) {
			ArrayList<DecoratedContentProposal> proposals = new ArrayList<DecoratedContentProposal>();

			if(possibleElementList != null) {
				Iterator it = possibleElementList.getElements().iterator();
				while(it.hasNext()) {
					final NamedElement element = (NamedElement)it.next();
					final String simpleName = element.getName();

					if( position < simpleName.length() && contents.substring(0, position).equalsIgnoreCase(simpleName.substring(0, position))) {
						proposals.add(new DecoratedContentProposal(element, labelProvider));
					}
				}
			}
			
			Collections.sort(proposals);
			return proposals.toArray(new DecoratedContentProposal[proposals.size()]);
		}
	}

	/**
	 * Label provider for metaclasses.
	 * 
	 * @author Remi Schnekenburger
	 */
	protected class MetaclassLabelProvider extends LabelProvider implements ITableLabelProvider {

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
		 */
		/**
		 * 
		 * 
		 * @param element 
		 * 
		 * @return 
		 */
		@Override
		public Image getImage(Object element) {
			Image image = null;
			if((element instanceof Class)) {
				image = PapyrusPlugin.getIconElement((Class)element);
			}
			// return the image if not null or the default stereotype image if stereotype has no image
			return (image != null) ? image : PapyrusPlugin.UML_LABEL_PROVIDER.getImage(Class.class, null) ;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
		 */
		/**
		 * 
		 * 
		 * @param element 
		 * 
		 * @return 
		 */
		@Override
		public String getText(Object element) {
			if(!(element instanceof Class)) {
				return "not a class";
			} else {
				return ((Class)element).getName();
			}
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
		 */
		/**
		 * 
		 * 
		 * @param element 
		 * @param columnIndex 
		 * 
		 * @return 
		 */
		public Image getColumnImage(Object element, int columnIndex) {
			if(columnIndex == 0) {
				return getImage(element);
			}
			return null;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
		 */
		/**
		 * 
		 * 
		 * @param element 
		 * @param columnIndex 
		 * 
		 * @return 
		 */
		public String getColumnText(Object element, int columnIndex) {
			if(columnIndex == 0) {
				return getText(element);
			} else if(columnIndex == 1) {
				return ((Class)element).getQualifiedName();
			}
			return "not the right column index";
		}
	}
	
	/**
	 * Label provider for stereotypes that modifies {@link MetaclassLabelProvider#getText(Object)}.
	 * It returns the qualified name of the Metaclass instead of the simple name.
	 * 
	 * @author Remi Schnekenburger
	 */
	protected class MetaclassQualifiedLabelProvider extends MetaclassLabelProvider {
		
		/* (non-Javadoc)
		 * @see com.cea.papyrus.core.ui.dialogs.ChooseSetStereotypeDialog.StereotypeLabelProvider#getText(java.lang.Object)
		 */
		/**
		 * 
		 * 
		 * @param element 
		 * 
		 * @return 
		 */
		public String getText(Object element) {
			if(!(element instanceof Class)) {
				return "not a class";
			} else {
				return ((Class)element).getQualifiedName();
			}
		}
	}
}
